falco 的規則部分可以參考 Falco 101 的 101.06 - Falco Rules Basics、101.07 - Falco Rules Deep Dive、101.08 - Fine Tuning Falco Rules (Exceptions)。
falco 安裝後會套用兩種規則,一種是內建規則,另一種則是自定義規則。位置分別是 /etc/falco/falco_rules.yaml 及 /etc/falco/falco_rules.local.yaml。
cat /etc/falco/falco_rules.yaml ;
cat /etc/falco/falco_rules.local.yaml ;
falco 規則內可以定義三種類型的元件,分別是 rule、macro 以及 list,這邊為了簡化學習部分只說明 rule 的部分。 rule 的概念很簡單,就是定義好觸發條件、輸出訊息就結束了,是不是還蠻簡單的(?),以下就是一個偵測開啟特權容器的規則。
- rule: Launch Privileged Container
desc: Detect the initial process started in a privileged container. Exceptions are made for known trusted images.
condition: >
container_started and container
and container.privileged=true
and not falco_privileged_containers
and not user_privileged_containers
and not redhat_image
output: Privileged container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag)
priority: INFO
tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement]
從上面各欄位的名稱大概都可以猜出該欄位的功能,其中比較重要的幾個大概就是 condition、output。 condition 的重點在於要知道有那些資料是可以用來當作觸發條件的,以及有哪些運算元可以使用。output 重點在於怎麼輸出一些變數的資訊,以及有哪些資訊是可以被輸出的。而官網早已整理好這些資訊,運算元部分可以參考Condition Syntax,可用資料部分可以參考 Supported Fields for Conditions and Outputs 或是用指令 falco --list=syscall。
之前測試沒辦法抓到 nsenter 指令的執行,所以這邊要一步步把整個抓取的規則給建置出來。
- rule: shell_in_container
desc: notice shell activity within a container
condition: >
evt.type in (execve,execveat) and
container.id != 'host' and
proc.name contains 'nsenter'
output: >
shell in a container
(user=%user.name container_id=%container.id container_name=%container.name
proc.name=%proc.name proc.pname=%proc.pname proc.cmdline=%proc.cmdline)
priority: INFORMATIONAL
docker run --rm -it --privileged --pid=host aeifkz/my-ubuntu:v1.0 bash ;
# 這樣會被抓到
$(tr "[A-Z]" "[a-z]"<<<"nSenTer") -m -u -i -n -p -t 1 bash ;
exit ;
cp $(which nsenter) my_nnn ;
# 這樣就看不到惹
./my_nnn -m -u -i -n -p -t 1 bash ;
exit ;
- rule: shell_in_container
desc: notice shell activity within a container
condition: >
evt.type in (execve,execveat) and
container.id != 'host'
and (proc.pname = "sh" or proc.pname = "bash")
output: >
shell in a container
(user=%user.name container_id=%container.id container_name=%container.name
proc.name=%proc.name proc.pname=%proc.pname proc.cmdline=%proc.cmdline)
priority: INFORMATIONAL